/*
 Copyright (c) 2013 MeherTJ G. All rights reserved.
 License: LGPL for personnal study or free software.
 */

#pragma once

#include <cstdint>

/**
  Brief: class MaskWrap<Int, Mask>
 encrypt integer values in memory.
  */

namespace Zen
{
#if defined(ZEN_WRAP_CODE)
	static constexpr uint64_t SecretCode = ZEN_WRAP_CODE;
#else
	// 1001 1100 1010 0101 1100 0011 1001 1110 0011 0001 0100 0110 0110 0011 1100 1001
	static constexpr uint64_t SecretCode = 0x9CA5'C39E'3146'63C9;
#endif

	/// <summary>
	/// use a mask to encrypt a native interger type in memory.
	/// </summary>
	/// <typeparam name="Type_"></typeparam>
	/// <typeparam name="Mask_"></typeparam>
	template <typename Type_, Type_ Mask_ = (Type_)SecretCode>
	class MaskWrap
	{
	public:
		using Integer = Type_;

	protected:
		Type_ mValue;

	public:
		MaskWrap(Type_ value = 0)
		{
			mValue = value ^ Mask_;
		}
		operator Type_() const
		{
			return mValue ^ Mask_;
		}
		MaskWrap& operator=(MaskWrap other)
		{
			mValue = other.mValue;
			return *this;
		}
		MaskWrap& operator*=(Type_ value)
		{
			mValue = ((mValue ^ Mask_) * value) ^ Mask_;
			return *this;
		}
		MaskWrap& operator/=(Type_ value)
		{
			mValue = ((mValue ^ Mask_) / value) ^ Mask_;
			return *this;
		}
		MaskWrap& operator+=(Type_ value)
		{
			mValue = ((mValue ^ Mask_) + value) ^ Mask_;
			return *this;
		}
		MaskWrap& operator-=(Type_ value)
		{
			mValue = ((mValue ^ Mask_) - value) ^ Mask_;
			return *this;
		}
		MaskWrap& operator<<=(Type_ value)
		{
			mValue = ((mValue ^ Mask_) << value) ^ Mask_;
			return *this;
		}
		MaskWrap& operator>>=(Type_ value)
		{
			mValue = ((mValue ^ Mask_) >> value) ^ Mask_;
			return *this;
		}
		MaskWrap& operator|=(Type_ value)
		{
			mValue = ((mValue ^ Mask_) | value) ^ Mask_;
			return *this;
		}
		MaskWrap& operator&=(Type_ value)
		{
			mValue = ((mValue ^ Mask_) & value) ^ Mask_;
			return *this;
		}
		MaskWrap& operator--()
		{
			mValue = ((mValue ^ Mask_) - 1) ^ Mask_;
			return *this;
		}
		MaskWrap& operator++()
		{
			mValue = ((mValue ^ Mask_) + 1) ^ Mask_;
			return *this;
		}
		Type_ operator++(int)
		{
			Type_ value = *this;
			mValue = ((mValue ^ Mask_) + 1) ^ Mask_;
			return value;
		}
		Type_ operator--(int)
		{
			Type_ value = *this;
			mValue = ((mValue ^ Mask_) - 1) ^ Mask_;
			return value;
		}
		Type_ const& InnerValue() const
		{
			return mValue;
		}
	};

	typedef MaskWrap<int64_t> Int64s;
	typedef MaskWrap<uint64_t> UInt64s;
	typedef MaskWrap<int32_t> Int32s;
	typedef MaskWrap<uint32_t> UInt32s;
	typedef MaskWrap<int16_t> Int16s;
	typedef MaskWrap<uint16_t> UInt16s;
	typedef MaskWrap<int8_t> Int8s;
	typedef MaskWrap<uint8_t> UInt8s;
} // namespace Zen
